home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 9 / FM Towns Free Software Collection 9.iso / t_os / tool / extdrv / src / buf_fat.c next >
C/C++ Source or Header  |  1994-11-16  |  7KB  |  311 lines

  1. #include "extdrv.h"
  2. #include "file.h"
  3. #include "dir.h"
  4. #include "buffer.h"
  5. #include "dos.h"
  6. #include "extern.h"
  7.  
  8. int n_fatbuf;
  9. struct fatbuf far *fat_base = NULL, far *fat_head = NULL, far *fat_tail = NULL;
  10. struct pbuf far *pfatbuf;
  11.  
  12. struct fatbuf far *get_fat(struct drvinfo far *d, u_long offset)
  13. {
  14.     int n;
  15.     u_short off, sector;
  16.     u_long sec;
  17.     u_long addr;
  18.     struct fatbuf far *p, far *free;
  19.  
  20.     free = NULL;
  21.     off = (u_short)(offset >> 11);
  22.     for (p = fat_head; p != NULL; p = p->next){
  23.         if (p->drv == d  &&  p->off == off){
  24.             if (p != fat_head){
  25.                 if ((p->prev->next = p->next) == NULL)
  26.                     fat_tail = p->prev;
  27.                 else
  28.                     p->next->prev = p->prev;
  29.                 p->next = fat_head;
  30.                 p->prev = NULL;
  31.                 fat_head->prev = p;
  32.                 fat_head = p;
  33.             }
  34.             return (p);
  35.         }
  36.         if (p->drv == NULL)
  37.             free = p;
  38.     }
  39. #ifdef DEBUG_FAT
  40.     auxputs(" FAT miss hit ");
  41.     auxprinthex(off);
  42.     auxputs(" ");
  43. #endif
  44.     if (free == NULL){
  45. #ifdef DEBUG_FAT
  46.         auxputs(" exhausted ");
  47. #endif
  48.         p = fat_tail;
  49.         if (p->pp != NULL){
  50.             if (p->pp->dirty){
  51.                 addr = p->buf + (p->pp->offset << LOGPBUFSIZ);
  52.                 xcopy(laddr(p->pp->data), addr, PBUFSIZE);
  53.                 p->dirty = TRUE;
  54.             }
  55.             p->pp->drv = NULL; /* invalidate */
  56.             p->pp = NULL;
  57.         }
  58.         if (p->dirty){
  59. #ifdef DEBUG_FAT
  60.             auxputs("flush FBUF#");
  61.             auxprinthex((u_long)((char far *)p - (char far *)fat_base)/sizeof (struct fatbuf));
  62.             auxputs(" ");
  63.             auxprinthex(p->off);
  64.             auxputs(" ");
  65.             auxprinthex(p->n_entry);
  66.             auxputs(" ");
  67. #endif
  68.             d = p->drv;
  69.             sector = FATBUFSIZ / d->sectsiz;
  70.             sector = d->fat_off + p->off * sector;
  71.             if (write2(d, (u_long)sector, FATBUFSIZ/d->blocksize, p->buf) != 0){
  72. #ifdef DEBUG_ERR
  73.                 auxputs("write error ");
  74. #endif
  75.                 return (NULL);
  76.             }
  77.             if (!d->fat_error){
  78. #ifdef DEBUG_FAT
  79.                 auxputs("dup fat ");
  80. #endif
  81.                 n = d->n_fat - 1;
  82.                 sec = (u_long)sector;
  83.                 while (--n >= 0){
  84.                     sec += d->fatsiz;
  85.                     if (write2(d, sec, FATBUFSIZ/d->blocksize, p->buf) != 0){
  86. #ifdef DEBUG_ERR
  87.                         auxputs("write error ");
  88. #endif
  89.                         return (NULL);
  90.                     }
  91.                 }
  92.             }
  93. #ifdef DEBUG_ERR
  94.             else {
  95.                 auxputs("FAT no-dup, because of fat_error\r\n");
  96.             }
  97. #endif
  98.             p->dirty = FALSE;
  99.         }
  100.         fat_tail = p->prev;
  101.         p->prev->next = NULL;
  102.         fat_head->prev = p;
  103.         p->next = fat_head;
  104.         p->prev = NULL;
  105.         fat_head = p;
  106.     } else {
  107.         if ((p = free) != fat_head){
  108.             if (p->next == NULL)
  109.                 fat_tail = p->prev;
  110.             else
  111.                 p->next->prev = p->prev;
  112.             p->prev->next = p->next;
  113.             fat_head->prev = p;
  114.             p->next = fat_head;
  115.             p->prev = NULL;
  116.             fat_head = p;
  117.         }
  118.     }
  119.     p->drv = d;
  120.     p->off = off;
  121.     if (off == d->fat_last_sec)
  122.         p->n_entry = d->fat_last_size;
  123.     else
  124.         p->n_entry = FATBUFSIZ;
  125.     sector = FATBUFSIZ / d->sectsiz;
  126.     sector = d->fat_off + off * sector;
  127.     if (read2(d, (u_long)sector, FATBUFSIZ/d->blocksize, p->buf) != 0){
  128. #ifdef DEBUG
  129.         auxputs("read error ");
  130. #endif
  131.         p->drv = NULL;
  132.         return (NULL);
  133.     }
  134. #ifdef DEBUG_FAT
  135.     auxputs("FBUF#");
  136.     auxprinthex((u_long)((char far *)p - (char far *)fat_base)/sizeof (struct fatbuf));
  137.     auxputs(" DISK-READ,");
  138.     auxprinthex(sector);
  139.     auxputs(",");
  140.     auxprinthex(p->n_entry);
  141.     auxputs(" ");
  142. #endif
  143.     return (p);
  144. }
  145.  
  146. fat_flush(struct drvinfo far *d, int invalidate)
  147. {
  148.     struct fatbuf far *p;
  149.     int n;
  150.     u_short sector;
  151.     u_long sec;
  152.     u_long addr;
  153.     
  154. #ifdef DEBUG
  155.     auxputs("flush_fat ");
  156. #endif
  157.     for (p = fat_head; p != NULL; p = p->next){
  158.         if (d == NULL  ||  p->drv == d){
  159.             if (p->pp != NULL  &&  p->pp->dirty){
  160.                 addr = p->buf + (p->pp->offset << LOGPBUFSIZ);
  161.                 xcopy(laddr(p->pp->data), addr, PBUFSIZE);
  162.                 p->pp->dirty = FALSE;
  163.                 p->dirty = TRUE;
  164.             }
  165.             if (p->dirty){
  166. #ifdef DEBUG
  167.                 auxputs("dirty ");
  168. #endif
  169.                 d = p->drv;
  170.                 sector = FATBUFSIZ / d->sectsiz;
  171.                 sector = d->fat_off + p->off * sector;
  172.                 if (write2(d, (u_long)sector, FATBUFSIZ/d->blocksize, 
  173.                             p->buf) != 0){
  174. #ifdef DEBUG_ERR
  175.                     auxputs("write error ");
  176. #endif
  177.                     return (-1);
  178.                 }
  179.                 if (!p->drv->fat_error){
  180.                     n = p->drv->n_fat - 1;
  181.                     sec = (u_long)sector;
  182.                     while (--n >= 0){
  183.                         sec += d->fatsiz;
  184.                         if (write2(d, sec, FATBUFSIZ/d->blocksize, 
  185.                                     p->buf) != 0){
  186. #ifdef DEBUG_ERR
  187.                             auxputs("write error ");
  188. #endif
  189.                             return (-1);
  190.                         }
  191.                     }
  192.                 }
  193. #ifdef DEBUG_ERR
  194.                 else {
  195.                     auxputs("FAT no-dup, because of fat_error\r\n");
  196.                 }
  197. #endif
  198.                 p->dirty = FALSE;
  199.             }
  200.             if (invalidate){
  201.                 if (p->pp != NULL){
  202.                     p->pp->drv = NULL;
  203.                     p->pp = NULL;
  204.                 }
  205.                 p->drv = NULL;
  206.             }
  207.         }
  208.     }
  209. #ifdef DEBUG
  210.     auxputs("done.\r\n");
  211. #endif
  212.     return (0);
  213. }
  214.  
  215. inv_fat(u_int devno)
  216. {
  217.     struct fatbuf far *p;
  218.     
  219.     for (p = fat_head; p != NULL; p = p->next){
  220.         if (p->drv->devno == devno){
  221.             if (p->pp != NULL){
  222.                 p->pp->drv = NULL;
  223.                 p->pp = NULL;
  224.             }
  225.             p->dirty = FALSE;
  226.             p->drv = NULL;
  227.         }
  228.     }
  229.     return (0);
  230. }
  231.  
  232. static struct pbuf far *get_pfatbuf(struct drvinfo far *d, long offset)
  233. {
  234.     int i;
  235.     struct pbuf far *pp;
  236.     struct fatbuf far *p;
  237.     u_long addr;
  238.     u_short off, offp;
  239.  
  240.     /* search primary buffer */
  241.     off = (u_short)(offset >> LOGFATBUFSIZ);
  242.     offp = (u_short)(offset >> LOGPBUFSIZ) & (NFATPBUF - 1);
  243.     for (i = 0, pp = pfatbuf; i < 2; i++, pp++)
  244.         if (pp->drv==d  &&  pp->id==off)
  245.             break;
  246.     if (i == 2  ||  offp != pp->offset){
  247.         if (i == 2){ /* not found */
  248.             pp = pfatbuf;
  249.             if (pp->age == 0)
  250.                 pp++;
  251.             if (pp->drv != NULL){
  252.                 if (pp->dirty){
  253.                     p = pp->buffer.fbuf;
  254.                     addr = p->buf + (pp->offset << LOGPBUFSIZ);
  255.                     xcopy(laddr(pp->data), addr, PBUFSIZE);
  256.                     p->dirty = TRUE;
  257.                 }
  258.                 pp->buffer.fbuf->pp = NULL;
  259.             }
  260.             if ((p = get_fat(d, offset)) == NULL){
  261. #ifdef DEBUG
  262.                 auxputs("fat_read: error\r\n");
  263. #endif
  264.                 pp->drv = NULL;
  265.                 return (NULL);
  266.             }
  267.             pp->drv = d;
  268.             pp->id = off;
  269.             pp->buffer.fbuf = p;
  270.             pp->buffer.fbuf->pp = pp;
  271.         } else {
  272.             p = pp->buffer.fbuf;
  273.             if (pp->dirty){
  274.                 addr = p->buf + (pp->offset << LOGPBUFSIZ);
  275.                 xcopy(laddr(pp->data), addr, PBUFSIZE);
  276.                 p->dirty = TRUE;
  277.             }
  278.         }
  279.         pp->offset = offp;
  280.         addr = p->buf + (offp << LOGPBUFSIZ);
  281.         xcopy(addr, laddr(pp->data), PBUFSIZE);
  282.         pp->dirty = FALSE;
  283.     }
  284.     pp->age = 0;
  285.     if (pp == pfatbuf)
  286.         (pfatbuf+1)->age = 1;
  287.     else
  288.         pfatbuf->age = 1;
  289.     return (pp);
  290. }
  291.  
  292. u_short fat_read(struct drvinfo far *d, long offset)
  293. {
  294.     struct pbuf far *pp;
  295.     
  296.     if ((pp = get_pfatbuf(d, offset)) == NULL)
  297.         return (1);
  298.     return (*(u_short far *)(pp->data + (offset & (PBUFSIZE - 1))));
  299. }
  300.  
  301. fat_write(struct drvinfo far *d, long offset, u_short fat)
  302. {
  303.     struct pbuf far *pp;
  304.     
  305.     if ((pp = get_pfatbuf(d, offset)) == NULL)
  306.         return (1);
  307.     pp->dirty = TRUE;
  308.     *(u_short far *)(pp->data + (offset & (PBUFSIZE - 1))) = fat;
  309.     return (0);
  310. }
  311.